#ifndef _ML307_APP_H_
#define _ML307_APP_H_

#include "ml307_api.h"

#if (_NETWOK_MODLE_TYPE_ == _ML307R_MODLE_) && (_NETWOK_FUNCTION_ENABLE_)

// 版本号字段长度
#define ML307_NUMBER_OF_VERSION                    (50ul)
// 设备序列号字段长度
#define ML307_NUMBER_OF_SERIAL_NUMBER              (50ul)

// 等待设备应答时间
#define ML307_WAIT_DEVICE_ACK_TIME                 (150ul)
// 发送超时时间
#define ML307_MESSAGE_SENGING_RATED_TIME           (250ul)
// 发送返回超时时间（长延时）
#define ML307_MESSAGE_SENDING_LONG_DELAY           (5000ul)

/**
 * @brief 报文解析结果
 *
 */
typedef enum
{
  ML307_EXECUTE_OVER,    // 完毕
  ML307_EXECUTE_WAIT,    // 等待
  ML307_EXECUTE_ERROR,   // 错误
  ML307_EXECUTE_RETRY,   // 重试
  ML307_EXECUTE_SUCCESS, // 成功
} Ml307CommandExecuteResult_t;

/**
 * @brief 硬件属性
 *
 */
typedef struct
{
  uint8_t Rssi;                                         // 信号强度
  char IMSICode[ML307_NUMBER_OF_VERSION];               // 卡片唯一令牌
  char VersionNumber[ML307_NUMBER_OF_VERSION];          // 版本号
  char IMEICode[ML307_NUMBER_OF_SERIAL_NUMBER];         // 模组序列号
  char CardSerialNumber[ML307_NUMBER_OF_SERIAL_NUMBER]; // 卡片序列号
} Ml307HardwareAttributes_t;

/**
 * @brief 报文发送步骤
 *
 */
typedef enum
{
  ML307_SENDINT_IDLE,                  // 发送空闲
  ML307_COMMECT_TEST,                  // 连接测试命令
  ML307_CLOSE_COMMADN_RETURN,          // 关闭命令回显
  ML307_GET_VERSION_NUMBER,            // 获取版本号
  ML307_GET_MANUFACTURER_INFORMATION,  // 获取厂商信息
  ML307_GET_IMSI_CODE,                 // 查询国际移动用户识别码
  ML307_GET_IMEI_CODE,                 // 查询国际移动设备识别码
  ML307_GET_CARD_INSERTED_STATUS,      // 查询检查 SIM 卡插入状态
  ML307_GET_CARD_ICCID_NUMBER,         // 获取卡片 ICCID
  ML307_GET_SIGNAL_STRENGTH,           // 查询信号强度
  ML307_GET_NETWORK_REGISTER_STATUS,   // 获取网络注册状态
  ML307_GET_NETWORK_ATTACHMENT_STATUS, // 获取网络附着状态
  ML307_GET_NETWORK_OPERATION,         // 获取网络运营商
  ML307_SET_NETWORK_OPERATION,         // 设置网络运营商
  ML307_CONFIG_DNS_SERVER,             // 配置 DNS 服务器
  ML307_DNS_SERVER_START,              // DNS 服务启动
  ML307_OPEN_TCP_SERVER,               // 打开 TCP 服务
  ML307_CLOSE_TCP_SERVER,              // 关闭 TCP 服务
  ML307_GET_TCP_CONNECT_STATUS,        // 获取 TCP 服务状态
  ML307_TCP_SWITCH_TRANSMISSION_MODE,  // TCP 切换传输模式
  ML307_TCP_EXIT_TRANSMISSION_MODE,    // TCP 退出传输模式
  ML307_CLOSE_MQTT_SERVER,             // 关闭 MQTT 服务
  ML307_OPEN_MQTT_SERVER,              // 打开 MQTT 服务
  ML307_SUBSCRIBE_MQTT_TOPICS,         // 订阅 MQTT 主题
  ML307_ALL_COMMAND_EXECUTED,          // 所有命令已执行
} Ml307StepsOfSending_t;

/**
 * @brief 状态位
 *
 */
typedef struct
{
  Ml307StepsOfSending_t StepsOfSending;
  uint8_t HostIpAddress[ML307_SERVER_ADDRESS_LENGTH];
} Ml307BitStatus_t;

/**
 * @brief 通讯初始化
 *
 */
/**
 * @brief 通讯初始化
 *
 */
extern void Ml307CommunicationsInitialization(void);

/**
 * @brief 过滤关键词
 *
 * @param pMessagePacket - 报文
 * @param pMessageSize   - 报文长度
 */
extern void Ml307FilterKeywords(const void *pMessagePacket, uint16_t *pMessageSize);

/**
 * @brief 构建自检报文
 *
 * @param pMessageOut      - 构建后的数据
 * @param pSizeOut         - 构建数据长度
 * @param pResponseTimeOut - 命令响应时间
 * @return bool            - 构建状态（true：成功 false：失败）
 */
extern bool Ml307BuildSelfTestMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut);

/**
 * @brief 构建初始化网络服务报文
 *
 * @param pMessageOut      - 构建后的数据
 * @param pSizeOut         - 构建数据长度
 * @param pResponseTimeOut - 命令响应时间
 * @return bool            - 构建状态（true：成功 false：失败）
 */
extern bool Ml307BuildInitiateNetAttachmentMessage(uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut);

/**
 * @brief 解析设备自检报文
 *
 * @param pDataIn  - 输入的数据流
 * @return uint8_t - 解析状态
 */
extern uint8_t Ml307ParsingSelfTestMessage(const void *pDataIn);

/**
 * @brief 解析初始化网络服务报文
 *
 * @param pDataIn  - 输入的数据流
 * @return uint8_t - 解析状态
 */
extern uint8_t Ml307ParsingInitiateNetAttachmentMessage(const void *pDataIn);

/**
 * @brief 获取模组固件版本号
 *
 * @param pVersionOut - 固件版本号
 */
extern void Ml307GetFirmwareVersion(char *pVersionOut);

/**
 * @brief 获取模组 IMEI 编码
 *
 * @param pImeiCodeOut - IMEI 编码
 */
extern void Ml307GetImeiCode(char *pImeiCodeOut);

/**
 * @brief 获取 SIM 卡 IMSI 编码
 *
 * @param pImsiCodeOut - IMSI 编码
 */
extern void Ml307GetImsiCode(char *pImsiCodeOut);

/**
 * @brief 获取 SIM 卡唯一编码
 *
 * @param pIccidOut - SIM 卡唯一编码
 */
extern void Ml307GetSimIccidCode(char *pIccidOut);

/**
 * @brief 获取无线信号强度
 *
 * @return uint8_t - 无线信号强度
 */
extern uint8_t Ml307GetSignalStrength(void);

/**
 * @brief 向服务器发送一点长度的数据
 *
 * @param pDataIn   - 待发送的数据
 * @param DataSize  - 待发送数据长度
 * @param pUartSend - 串口发送回调
 */
extern void Ml307SendDataToServer(const uint8_t *pDataIn, uint16_t DataSize, bool (*pUartSend)(const uint8_t *, uint16_t));

/**
 * @brief 解析 MQTT 主题推送的报文
 * 
 * @param pRxMessage    - 接收报文数据流
 * @param MessageLenght - 报文长度
 * @return bool         - 解析状态(true：成功 false：失败)
 */
extern bool Ml307ParsingMqttTopicPushMessages(const void *pRxMessage, uint16_t MessageLenght);

/**
 * @brief 解析接收报文有效性
 *
 * @param pRxMessage    - 接收报文数据流
 * @param MessageLenght - 报文长度
 * @return uint8_t      - 报文类型
 */
extern uint8_t Ml307ParsingIncomingMessageValidity(const void *pRxMessage, uint16_t MessageLenght);

#endif
#endif
